package com.rhcloud.insongr.srv.wechat.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.Writer;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.rhcloud.insongr.srv.wechat.bean.AccessTokenBean;
import com.rhcloud.insongr.srv.wechat.bean.WeChatReqBean;
import com.rhcloud.insongr.srv.wechat.bean.WeChatRespBean;
import com.rhcloud.insongr.srv.wechat.common.Constants;
import com.rhcloud.insongr.srv.wechat.constant.AppConstant;
import com.rhcloud.insongr.srv.wechat.task.TokenThread;
import com.rhcloud.insongr.srv.wechat.util.DownloadFileFromServer;
import com.rhcloud.insongr.srv.wechat.util.WeixinUtil;
import com.rhcloud.insongr.srv.yahoo.geocode.Query;
import com.rhcloud.insongr.srv.yahoo.weather.YahooWeather;
import com.rhcloud.insongr.srv.yahoo.weather.yweather.Forecast;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

@WebServlet(urlPatterns = "/WeChatServlet")
public class WeChatServlet extends HttpServlet {
	private static final long serialVersionUID = -2776902810130266533L;
	private static Log log = LogFactory.getLog(WeixinUtil.class);

	
	
	@Override
	public void init() throws ServletException {
		 // 未配置appid、appsecret时给出提示    
        if ("".equals(AppConstant.APPID) || "".equals(AppConstant.APPSECRET)) {
            log.error("appid and appsecret configuration error, please check carefully.");    
        } else {
            // 启动定时获取access_token的线程    
            new Thread(new TokenThread()).start();
        } 
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
//		String signature = req.getParameter("signature");
//		String timestamp = req.getParameter("timestamp");
//		String nonce = req.getParameter("nonce");
//		String echostr = req.getParameter("echostr");
//		// 此处需要检验signature对网址接入合法性进行校验。
//		// 没看出来有什么用，没弄。
//		// 详见：<a href="http://mp.weixin.qq.com/cgi-bin/readtemplate?t=wxm-callbackapi-doc&lang=zh_CN">文档</a>
//		log.info(signature + " : " + timestamp + " : " + nonce + " : " + echostr);
//		PrintWriter out = resp.getWriter();
//		out.write(echostr);
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		String echostr = request.getParameter("echostr");
		System.out.println(AppConstant.TOKEN+"|"+timestamp+"|"+nonce);
		String[] params = new String[]{AppConstant.TOKEN,timestamp,nonce};
		Arrays.sort(params);//升序
		String joinStr = "";
		for(int i=0;i<params.length;i++){
			joinStr += params[i];
		}
		if(signature.equals(makesha1(joinStr))){
			writer.write(echostr);
		}
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		Scanner scanner = new Scanner(req.getInputStream(), "utf-8");
		resp.setContentType("application/xml");
		resp.setCharacterEncoding("UTF-8");
		PrintWriter out = resp.getWriter();
		try {
			// 1、获取用户发送的信息
			StringBuffer sb = new StringBuffer(100);
			while (scanner.hasNextLine()) {
				sb.append(scanner.nextLine());
			}
			
			// 2、解析用户的信息
			JAXBContext jc = JAXBContext.newInstance(WeChatReqBean.class);
			Unmarshaller u = jc.createUnmarshaller();	//解包
			System.out.println("sb:"+sb);
			WeChatReqBean reqBean = (WeChatReqBean) u.unmarshal(new StringReader(sb.toString()));
			
			// 3、判定用户是否发的是地理位置的PO，并查询天气
			String content = getContent(reqBean);
			
			// 4、创建一个回复消息
			jc = JAXBContext.newInstance(WeChatRespBean.class);
			Marshaller m = jc.createMarshaller();		//打包，序列化
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			m.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
				@Override
				public void escape(char[] arg0, int arg1, int arg2, boolean arg3,
						Writer arg4) throws IOException {
					arg4.write(arg0, arg1, arg2);
				}
			});
			m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
			WeChatRespBean respBean = createRespBean(reqBean, content);
			FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\项目相关笔记\\respons_msg.txt"), true);
			m.marshal(respBean, fos);
			m.marshal(respBean, out);
			out.flush();
		} catch (JAXBException e) {
			e.printStackTrace();
			log.info(e.getMessage());
		} finally {
			if (scanner != null) {
				scanner.close();
				scanner = null;
			}
			if (out != null) {
				out.close();
				out = null;
			}
		}
	}

	/**
	 * @param reqBean
	 * @param content
	 * @return
	 */
	private WeChatRespBean createRespBean(WeChatReqBean reqBean, String content) {
		WeChatRespBean respBean = new WeChatRespBean();
		respBean.setFromUserName(reqBean.getToUserName());
		respBean.setToUserName(reqBean.getFromUserName());
		respBean.setMsgType("text");
		respBean.setCreateTime(new Date().getTime());
		respBean.setContent(content);
		return respBean;
	}

	/**
	 * @param reqBean
	 * @throws JAXBException
	 * @throws IOException 
	 */
	private String getContent(WeChatReqBean reqBean) throws JAXBException, IOException {
		StringBuffer content = new StringBuffer("亲，");
		String msgType = reqBean.getMsgType();
		if (msgType.equals(Constants.MSGTYPE_TEXT)) {
			if ("Hello2BizUser".equals(reqBean.getContent())) {
				// 这是新用户关注时默认发的一条信息。可以做一个欢迎处理。
				content.append("这是一个测试哈。想查天气，给我发一个地理位置的PO。[愉快]");
			} else {
				content.append("我没功夫和你聊天，我很忙的。想查天气，给我发一个地理位置的PO。[右哼哼]");
			}
		}else if(Constants.MSGTYPE_LOCATION.equals(msgType)){
			// 此处先调用Yahoo的PlaceFinder服务，获取用户当前所在地的woeid。
			// 再调用Yahoo的Weather服务获取天气情况。
			// 如果用兴趣，可以尝试做一个小黄鸡的服务。<a href="http://developer.simsimi.com/api">小黄鸡</a>
//			String placeUrl = "http://where.yahooapis.com/geocode?location=" + reqBean.getLocation_X() + "+" + reqBean.getLocation_Y() + "&gflags=R";
	        String placeUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%22" + 
	        		reqBean.getLocation_X() + "," + reqBean.getLocation_Y() + "%22%20and%20gflags=%22R%22";
//			String placeUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%2229.35,106.33%22%20and%20gflags=%22R%22";
			
	        
			JAXBContext jc = JAXBContext.newInstance(Query.class);
			Unmarshaller u = jc.createUnmarshaller();
			URL url = new URL(placeUrl);
			Query resultSet = (Query) u.unmarshal(url);	//读入此url的xml文件
			content.append(resultSet.getResults().getResult().getCity() + "：");
			
			String weatherUrl = String.format("http://weather.yahooapis.com/forecastrss?w=%s&u=c", resultSet.getResults().getResult().getWoeid());
//			String weatherUrl = String.format("http://weather.yahooapis.com/forecastrss?w=%s&u=c", "2158434");
			jc = JAXBContext.newInstance(YahooWeather.class);
			u = jc.createUnmarshaller();
			url = new URL(weatherUrl);
			YahooWeather weather = (YahooWeather) u.unmarshal(url);
			List<Forecast> list = weather.getChannel().getItem().getForecasts();
			content.append("今天最低温度" + list.get(0).getLow() + "℃，最高温度" + list.get(0).getHigh() + "℃；");
			content.append("明天最低温度" + list.get(1).getLow() + "℃，最高温度" + list.get(1).getHigh() + "℃。");
			if (list.get(0).getHigh() <= 15 || list.get(1).getHigh() <= 15) {
				content.append("天凉，注意保暖哦。");
			} else if(list.get(0).getHigh() <= 25 || list.get(1).getHigh() <= 25) {
				if (list.get(0).getCode() >= 26 && list.get(0).getCode() <= 32) {
					content.append("晴空万里，出去走走吧。");
				}
			} else {
				content.append("出去看看大街上的黑丝吧。");
			}
		}else if(Constants.MSGTYPE_IMAGE.equals(msgType)){
			content.append("好漂亮的图片。[色]");
		}else if(Constants.MSGTYPE_VOICE.equals(msgType)){
			//下载音频文件
			String mediaId = reqBean.getMediaId();
			AccessTokenBean accessTokenBean = AccessTokenBean.getInstance();
			String urlPath = AppConstant.MEDIA_DOWNLOAD_URL.replace("ACCESS_TOKEN", accessTokenBean.getAccess_token())
					.replace("MEDIA_ID", mediaId);
			String filePath = "C:\\Users\\Administrator\\Desktop\\项目相关笔记\\wx\\myvoice."+reqBean.getFormat();
			DownloadFileFromServer.downloadFile(urlPath, filePath);
		}else{
			content.append("想查天气，请给我发一个地理位置的PO。");
		}
		return content.toString();
	}
	
	public static String makesha1(String password) {
		MessageDigest md;
		try {
			// 生成一个sha1加密计算摘要
			md = MessageDigest.getInstance("sha1"); // 同样可以使用md5
			// 计算md5函数
			md.update(password.getBytes());
			// digest()最后确定返回sha1 hash值，返回值为8位字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
			// BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
			String pwd = new BigInteger(1, md.digest()).toString(16); //参数也可不只用16可改动,当然结果也不一样了
			return pwd;
		} catch (Exception e) {
			e.printStackTrace();
		}
			return password;
	}
	
	
//	public static void main(String[] args) {
//		String a = makesha1("kk");
//		System.out.println(a.length());
//		System.out.println(a);
//		
//		try {
//			MessageDigest.getInstance("sha1").digest();
//		} catch (NoSuchAlgorithmException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		
//		String b = makesha1Two("kk");
//		System.out.println(b.length());
//		System.out.println(b);
//	}
	
	public static String makesha1Two(String password) {
		MessageDigest md;
		try {
			md = MessageDigest.getInstance("sha1"); 
			
			md.update(password.getBytes());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
			return password;
	}
	
	

	public static void main(String[] args) throws Exception{
//		System.out.println(null+"--"+null);
//		String[] strs = new String[]{null,null,null};
//		Arrays.sort(strs);
//		String placeUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.placefinder%20where%20text=%2229.35,106.33%22%20and%20gflags=%22R%22";
		
		String placeuri = "http://query.yahooapis.com/v1/public/yql?q=select * from geo.placefinder where text=\"29.35,106.33\" and gflags = \"R\"";
		String placeUrl = placeuri.replaceAll(" ", "%20");
//		placeUrl = placeUrl.replaceAll("\"", "%22");
		System.out.println(placeUrl);
		
        
		JAXBContext jc = JAXBContext.newInstance(Query.class);
		Unmarshaller u = jc.createUnmarshaller();
		URL url = new URL(placeUrl);
		Query resultSet = (Query) u.unmarshal(url);	//读入此url的xml文件
		StringBuilder content = new StringBuilder("亲：");
		content.append(resultSet.getResults().getResult().getCity() + "：");
		
		String weatherUrl = String.format("http://weather.yahooapis.com/forecastrss?w=%s&u=c", resultSet.getResults().getResult().getWoeid());
//		String weatherUrl = String.format("http://weather.yahooapis.com/forecastrss?w=%s&u=c", "2158434");
		jc = JAXBContext.newInstance(YahooWeather.class);
		u = jc.createUnmarshaller();
		url = new URL(weatherUrl);
		YahooWeather weather = (YahooWeather) u.unmarshal(url);
		List<Forecast> list = weather.getChannel().getItem().getForecasts();
		content.append("今天最低温度" + list.get(0).getLow() + "℃，最高温度" + list.get(0).getHigh() + "℃；");
		content.append("明天最低温度" + list.get(1).getLow() + "℃，最高温度" + list.get(1).getHigh() + "℃。");
		
		System.out.println(content);
	}

}
